var events = require('events');
var util = require('util');
require('timers');

/**
 * @author jmanero
 * @returns {TaskManager}
 * 
 * Manages all tasks and events for an application. Includes a list of periodic
 * tasks, and methods to manage them.
 * 
 */
var TaskManager = function(callback) {
	events.EventEmitter.call(this);

	this.list = {};

	if(typeof(callback) == 'function') callback();
	return this;
};

util.inherits(TaskManager, events.EventEmitter);

/**
 * Insert a Task into the internal task list
 * 
 * @param task
 * @TODO This module still sucks. It needs to have less parameters.
 */
TaskManager.prototype.add = function(name, type, when, callback) {
	this.list[name] = new Task(name, type, when, callback);
	return this;
};

/**
 * Atempt to locate a Task in the internal task list
 * 
 * @param name
 * 
 * @throws Error
 *             If specified task does not exist
 * @returns Task
 */
TaskManager.prototype.get = function(name) {
	if (typeof (this.list[name]) != "object")
		throw Error("TaskManager.get: Task " + name + " does not exist!");

	return this.list[name];
};

/**
 * Stop specified task and remove its reference from the internal task list
 * 
 * @param name
 * 
 * @throws Error
 *             If specified task does not exist
 */
TaskManager.prototype.remove = function(name) {
	if (typeof (this.list[name]) != "object")
		throw Error("TaskManager.remove: Task " + name + " does not exist!");

	this.list[name].remove();
	delete (this.list[name]);
	
	return this;
};

/**
 * @author jmanero
 * @param name
 * @param type
 * @param when
 * @param callback
 * @returns {Task}
 * 
 * Data structure for a periodic task
 * 
 */
Task = function(name, type, when, callback) {
	if (typeof (name) !== "string" || typeof (type) !== "string"
			|| type !== 'listener' && typeof (when) !== "number"
			|| type === 'listener' && typeof (when) !== "string"
			|| typeof (callback) !== "function")
		throw TypeError("Task.new requires four argumants: 'string', 'string', 'number', 'function'");

	this.name = name;
	this.type = type;
	this.callback = callback;
	this.when = when;
	this.run = true;

	switch (this.type) {
	case 'periodic':
		this.handle = setInterval(this.callback, this.when);
		break;
	case 'single':
		this.handle = setTimeout(this.callback, this.when);
	case 'listener':
		this.on(this.when, this.callback);
	}

	return this;
};

/**
 * Stop Task from executing at next trigger
 * 
 * @returns {Task}
 */
Task.prototype.suspend = function() {
	if (!this.run)
		return this;

	switch (this.type) {
	case 'periodic':
		clearInterval(this.handle);
		break;
	case 'single':
		clearTimeout(this.handle);
	case 'listener':
		this.removeListener(this.when, this.callback);
	}

	this.run = false;

	return this;
};

/**
 * Resume execution of Task at next trigger
 * 
 * @returns {Task}
 */
Task.prototype.resume = function() {
	if (this.run)
		return this;

	switch (this.type) {
	case 'periodic':
		this.handle = setInterval(this.callback, this.when);
		break;
	case 'single':
		this.handle = setTimeout(this.callback, this.when);
	case 'listener':
		this.on(this.when, this.callback);
	}

	this.run = true;

	return this;
};

/**
 * Prepare Task for deletion
 * 
 */
Task.prototype.remove = function() {
	this.suspend();

	return this;
};

module.exports = TaskManager;
